package threading_webserver;

import java.net.*;
import java.util.logging.Level;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.*;
import javax.net.ssl.*;

public class Server extends Thread {

    private final Logger logger;
    private final ServerView gui;
    private final String name;
    private final int port;
    private final PortListener listener;
    private BufferedReader input;
    private DataOutputStream output;
    private final int MAXTHREADS = 20;
    public static int activeThreads = 0;
    //private SSLServerSocketFactory factory;
    //private SSLServerSocket serversocket;
    private ServerSocket serversocket;
    private boolean running = true;

//Port: Default 8080
    public Server(String name, int port, ServerView gui, PortListener listener, Logger logger) {
        this.gui = gui;
        this.port = port;
        this.name = name;
        this.listener = listener;
        this.logger = logger;

        //System.setProperty("javax.net.ssl.keyStore",Settings.webRoot + "\\keystore.jks");
        //System.setProperty("javax.net.ssl.keyStorePassword","123456");
        this.start();
    }

    public int getPort() {
        return this.port;
    }

    public ServerView getView() {
        return this.gui;
    }

    public BufferedReader getReader() {
        return this.input;
    }

    public DataOutputStream getOutput() {
        return this.output;
    }

    public void log(String s2) {
        gui.send_message_to_window(s2 + "\n");
    }

    public void deleteServersocket() {
        try {
            serversocket.close();
            running = false;
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        //SSLContext sslContext = null;
        serversocket = null;
        System.setProperty("javax.net.debug", "all");
        log(name + " starting...");

        try {
            log("\nTrying to bind to localhost on port " + port + "...");

//            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
//            File f = new File(Settings.webRoot + "\\cacerts.jks");
//            InputStream in = new FileInputStream(f);
//            char[] password = "123456".toCharArray();
//            ks.load(in, password);
//            in.close();
//            
//            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
//            kmf.init(ks, password);
//            
//            sslContext = SSLContext.getInstance("SSL");
//            sslContext.init(kmf.getKeyManagers(), null, null);
//            
//            this.factory = sslContext.getServerSocketFactory(); //(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
            //make a ServerSocket and bind it to given port
            //serversocket = (SSLServerSocket)factory.createServerSocket(port);
            serversocket = new ServerSocket(port);
        } catch (Exception e) {
            log("\nFatal Error:" + e.getMessage());
            return;
        }

        log("OK!\n");

        //wait for connections, process request, send response
        while (running) {
            log("\nReady, Waiting for requests...\n");
            try {
                //this call waits/blocks until someone connects to the port we are listening to
                //SSLSocket connectionsocket = (SSLSocket)serversocket.accept();
                Socket connectionsocket = serversocket.accept();
                
                //ipadress from client
                InetAddress client = connectionsocket.getInetAddress();
                log(client.getHostAddress() + " connected to server.\n");

                //Read the http header-request from the client from the socket interface into a buffer.
                input = new BufferedReader(new InputStreamReader(connectionsocket.getInputStream()));
                //Prepare a outputstream from us to the client, this will be used sending back our response (header + requested file) to the client.
                output = new DataOutputStream(connectionsocket.getOutputStream());

                log("active threads: " + activeThreads);
                if(activeThreads < MAXTHREADS)
                {
                    new Http_Handler(this, input, output, client.getHostAddress(), listener, logger);
                    activeThreads++;
                }
                else log("Too many threads!");
            } catch (Exception e) {
                log("\nError:" + e.getMessage());
            }
        }
    }
}
